1 /*
2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021
3 License:   [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License].
4 Authors: Marcelo S. N. Mancini
5 
6 	Copyright Marcelo S. N. Mancini 2018 - 2021.
7 Distributed under the CC BY-4.0 License.
8    (See accompanying file LICENSE.txt or copy at
9 	https://creativecommons.org/licenses/by/4.0/
10 */
11 
12 module hip.api.graphics.color;
13 
14 ///This struct is ubyte[4] or uint depending on your usages
15 struct HipColor
16 {
17     @"format" string toString() @nogc const {return "Color($r, $g, $b, $a)"; }
18     union 
19     {
20         struct {ubyte r, g, b, a;}
21         ubyte[4] values;
22         uint value;
23     }
24     this(ubyte r, ubyte g, ubyte b){values = [r,g,b,255];}
25     this(ubyte r, ubyte g, ubyte b, ubyte a){values = [r,g,b,a];}
26     this(float r, float g, float b, float a){values = [cast(ubyte)(r*255),cast(ubyte)(g*255),cast(ubyte)(b*255),cast(ubyte)(a*255)];}
27     this(ubyte[4] rgba){values = rgba;}
28     this(uint rgba){values = unpackRGBA(rgba);}
29 
30 
31     static HipColor alpha(ubyte alpha){return HipColor(255, 255, 255, alpha);}
32     static HipColor alpha(float alpha){return HipColor(255, 255, 255, cast(ubyte)(alpha*255));}
33     static enum white   = HipColor(0xffffffff);
34     static enum black   = HipColor(0x000000ff);
35     static enum red     = HipColor(0xff0000ff);
36     static enum green   = HipColor(0x00ff00ff);
37     static enum blue    = HipColor(0x0000ffff);
38     static enum yellow  = HipColor(0xffff00ff);
39     static enum purple  = HipColor(0xff00ffff);
40     static enum teal    = HipColor(0x00ffffff);
41     static enum no      = HipColor(0x00000000);
42 
43     alias values this;
44 
45     HipColor lerp(HipColor to, float t) const
46     {
47         float fromT = 1.0 - t;
48 
49         ushort nR = cast(ushort)(fromT*r + t*to.r);
50         ushort nG = cast(ushort)(fromT*g + t*to.g);
51         ushort nB = cast(ushort)(fromT*b + t*to.b);
52         ushort nA = cast(ushort)(fromT*a + t*to.a);
53 
54         return HipColor(
55             cast(ubyte)(nR > 255 ? 255 : nR),
56             cast(ubyte)(nG > 255 ? 255 : nG),
57             cast(ubyte)(nB > 255 ? 255 : nB),
58             cast(ubyte)(nA > 255 ? 255 : nA),
59         );
60     }
61 
62 }
63 
64 
65 /** 
66  *  A struct containing a HipColor and a T which describes what color is in this T.
67  *  This is useful for doing color interpolation and gradients.
68  */
69 struct HipColorStop
70 {
71     HipColor color;
72     float t = 0;
73 }
74 
75 /** 
76  * 
77  * Params:
78  *   colorStops = A sorted array of color stops.
79  *   t = What is the current T. Ranging from 0 to 1
80  * Returns: The lerped color in the stop.
81  */
82 HipColor gradientColor(const scope ref HipColorStop[] colorStops, float t)
83 {
84     if(colorStops.length == 0) return HipColor.no;
85     if(t >= 1) return colorStops[$-1].color;
86     for(uint i = 1 ; i < colorStops.length; i++)
87     {
88         if(t > colorStops[i].t) continue;
89         float currLerpT = t / (colorStops[i].t - colorStops[i-1].t);
90         return colorStops[i-1].color.lerp(colorStops[i].color, currLerpT);
91     }
92     return colorStops[$-1].color;
93 }
94 
95 /**
96 *   This construct is compatible with float[4] when setting a shader variable.
97 */
98 struct HipColorf
99 {
100     union
101     {
102         struct
103         {
104             float r =0, g = 0, b = 0, a = 0;
105         }
106         float[4] values;
107     }
108     this(HipColor c){values = [cast(float)c.r / 255, cast(float)c.g/255, cast(float)c.b/255, cast(float)c.a/255];}
109     this(float r, float g, float b, float a){values = [r,g,b,a];}
110     ubyte[4] unpackRGBA()
111     {
112         return [cast(ubyte)(r*255), cast(ubyte)(g*255), cast(ubyte)(b*255), cast(ubyte)(a*255)];
113     }
114 
115     uint toInteger()
116     {
117         ubyte red = cast(ubyte)(r*255);
118         ubyte green = cast(ubyte)(g*255);
119         ubyte blue = cast(ubyte)(b*255);
120         ubyte alpha = cast(ubyte)(a*255);
121         return packRGBA(red,green,blue,alpha);
122     }
123 
124     static HipColorf fromInt(uint color)
125     {
126         ubyte[4] c = hip.api.graphics.color.unpackRGBA(color);
127 
128         return HipColorf(
129             (cast(float)c[0])/255,
130             (cast(float)c[1])/255,
131             (cast(float)c[2])/255,
132             (cast(float)c[3])/255
133         );
134     }
135 
136     auto opAssign(in HipColorf color)
137     {
138         values[] = color.values[];
139         return this;
140     }
141     
142     static enum invalid = HipColorf(-1, -1, -1, -1);
143     static enum white   = HipColorf(1,1,1,1);
144     static enum black   = HipColorf(0,0,0,1);
145     static enum red     = HipColorf(1,0,0,1);
146     static enum green   = HipColorf(0,1,0,1);
147     static enum blue    = HipColorf(0,0,1,1);
148     static enum yellow  = HipColorf(1,1,0,1);
149     static enum purple  = HipColorf(1,0,1,1);
150     static enum teal    = HipColorf(0,1,1,1);
151     static enum no      = HipColorf(0,0,0,0);
152 
153     alias values this;
154 }
155 
156 uint packRGBA(ubyte r, ubyte g, ubyte b, ubyte a)
157 {
158     return ((r << 24) + (g << 16) + (b << 8) + a);
159 }
160 
161 ubyte[4] unpackRGBA(uint rgba)
162 {
163     return
164     [
165         rgba >> 24,
166         (rgba >> 16) & 255,
167         (rgba >> 8) & 255,
168         rgba & 255
169     ];
170 }
171 
172 pragma(inline, true)
173 {
174     HipColorf color(float[4] c){ return HipColorf(c[0], c[1], c[2], c[3]); }
175     HipColorf color(float r, float g, float b, float a = 1.0){ return HipColorf(r,g,b,a); }
176 
177     HipColor color(ubyte r, ubyte g, ubyte b, ubyte a = 255){return HipColor(r,g,b,a);}
178     HipColor color(uint c)
179     {
180         ubyte[4] rgba = unpackRGBA(c);
181         return HipColor(rgba[0], rgba[1], rgba[2], rgba[3]);
182     }
183 }